package org.summer.lawyer.domain.vo.payorder;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import io.github.linpeilie.annotations.AutoMapper;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.summer.lawyer.constant.enums.PayOrderStatus;
import org.summer.lawyer.domain.PayOrder;

import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;



/**
 * 支付订单视图对象 pay_order
 *
 * @author summer
 * @date 2024-06-22
 */
@Schema(title ="支付订单视图对象 pay_order", description = "支付订单视图对象 pay_order")
@Data
@AutoMapper(target = PayOrder.class)
public class PayOrderVo implements Serializable{

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 主键ID
     */
    @Schema(title = "id", type = "Long", description = "主键ID")
    private Long id;

    /**
     * 支付应用ID
     */
    @Schema(title = "appId", type = "Long", description = "支付应用ID")
    private Long appId;

    /**
     * 微信appid
     */
    @Schema(title = "wxAppId", type = "String", description = "微信appid")
    private String wxAppId;

    /**
     * 商户号
     */
    @Schema(title = "mchNo", type = "String", description = "商户号")
    private String mchNo;

    /**
     * 商户名称
     */
    @Schema(title = "mchName", type = "String", description = "商户名称")
    private String mchName;

    /**
     * 通道ID
     */
    @Schema(title = "channelId", type = "Long", description = "通道ID")
    private Long channelId;

    /**
     * 通道编码
     */
    @Schema(title = "channelCode", type = "String", description = "通道编码")
    private String channelCode;

    /**
     * 用户ID
     */
    @Schema(title = "userId", type = "Long", description = "用户ID")
    private Long userId;

    /**
     * 用户openId
     */
    @Schema(title = "openId", type = "String", description = "用户openId")
    private String openId;

    /**
     * 支付单号
     */
    @Schema(title = "payNo", type = "String", description = "支付单号")
    private String payNo;

    /**
     * 第三方交易号
     */
    @Schema(title = "tradeNo", type = "String", description = "第三方交易号")
    private String tradeNo;

    /**
     * 订单ID
     */
    @Schema(title = "orderId", type = "Long", description = "订单ID")
    private Long orderId;

    /**
     * 商品标题
     */
    @Schema(title = "subject", type = "String", description = "商品标题")
    private String subject;

    /**
     * 商品描述
     */
    @Schema(title = "body", type = "String", description = "商品描述")
    private String body;

    /**
     * 付款方式（10微信，20支付宝，30银行卡）
     */
    @Schema(title = "payWay", type = "String", description = "付款方式（10微信，20支付宝，30银行卡）")
    private String payWay;

    /**
     * 支付状态（1支付成功，2支付失败）
     */
    @Schema(title = "payStatus", type = "Integer", description = "支付状态（1支付成功，2支付失败）")
    private Integer payStatus;

    /**
     * 支付时间
     */
    @Schema(title = "payTime", type = "Date", description = "支付时间")
    private Date payTime;

    /**
     * 步骤(1 创建支付，2 支付回调通知)
     */
    @Schema(title = "payStep", type = "Integer", description = "步骤(1 创建支付，2 支付回调通知)")
    private Integer payStep;

    /**
     * 请求支付状态（请求支付状态，1成功，2失败）
     */
    @Schema(title = "postStatus", type = "Integer", description = "请求支付状态（请求支付状态，1成功，2失败）")
    private Integer postStatus;

    /**
     * 回调状态（1成功，2失败）
     */
    @Schema(title = "returnStatus", type = "Integer", description = "回调状态（1成功，2失败）")
    private Integer returnStatus;

    /**
     * 支付金额（单位分）
     */
    @Schema(title = "amount", type = "Long", description = "支付金额（单位分）")
    private Long amount;

    /**
     * 退款金额
     */
    @Schema(title = "refundPrice", type = "Long", description = "退款金额")
    private Long refundPrice;

    /**
     * 第三方返回的错误码
     */
    @Schema(title = "resultCode", type = "String", description = "第三方返回的错误码")
    private String resultCode;

    /**
     * 第三方返回的错误信息
     */
    @Schema(title = "resultMsg", type = "String", description = "第三方返回的错误信息")
    private String resultMsg;

    /**
     * 提交的信息
     */
    @Schema(title = "postJson", type = "String", description = "提交的信息")
    private String postJson;

    /**
     * 回调的信息
     */
    @Schema(title = "returnJson", type = "String", description = "回调的信息")
    private String returnJson;

    /**
     * 回调时间
     */
    @Schema(title = "returnTime", type = "Date", description = "回调时间")
    private Date returnTime;

    /**
     * 回调地址
     */
    @Schema(title = "notifyUrl", type = "String", description = "回调地址")
    private String notifyUrl;

    /**
     * 手续费比率（千位比，1/1000）
     */
    @Schema(title = "procedureKb", type = "Long", description = "手续费比率（千位比，1/1000）")
    private Integer procedureKb;

    /**
     * 手续费（单位分）
     */
    @Schema(title = "procedureFee", type = "Long", description = "手续费（单位分）")
    private Long procedureFee;

    /**
     * 订单退款成功时间
     */
    @Schema(title = "successTime", type = "Date", description = "订单退款成功时间")
    private LocalDateTime successTime;

    /**
     * 扩展参数
     */
    @Schema(title = "extParam", type = "String", description = "扩展参数")
    private String extParam;

    /**
     * 原始的同步/异步通知结果
     */
    @JsonIgnore
    @Schema(title = "rawData", type = "Object", description = "原始的同步/异步通知结果")
    private Object rawData;

    /**
     * 时间戳
     */
    @Schema(title = "timeStamp", type = "String", description = "时间戳")
    private String timeStamp;

    /**
     * 随机字符串，不长于32位
     */
    @Schema(title = "nonceStr", type = "String", description = "随机字符串")
    private String nonceStr;

    /**
     * 小程序下单接口返回的prepay_id参数值，提交格式如：prepay_id=***
     */
    @Schema(title = "packageValue", type = "String", description = "小程序下单接口返回的prepay_id参数值，提交格式如：prepay_id=***")
    private String packageValue;

    /**
     * 签名类型，默认为RSA，仅支持RSA
     */
    @Schema(title = "packageValue", type = "String", description = "签名类型，默认为RSA，仅支持RSA")
    private String signType;

    /**
     * 签名，使用字段appid、timeStamp、nonceStr、package计算得出的签名值
     * 签名所使用的appid，为【小程序下单】时传入的appid，微信支付会校验下单与调起支付所使用的appid的一致性。
     */
    @Schema(title = "paySign", type = "String", description = "签名，使用字段appid、timeStamp、nonceStr、package计算得出的签名值")
    private String paySign;


    public static PayOrderVo pendingOf(String payNo, Object rawData){
        PayOrderVo vo = new PayOrderVo();
        vo.setPayStatus(PayOrderStatus.PENDING.getCode());
        vo.setPayNo(payNo);
        vo.setRawData(rawData);
        vo.setReturnJson(JSONUtil.toJsonStr(rawData));
        vo.setNonceStr(((WxPayUnifiedOrderV3Result.JsapiResult)rawData).getNonceStr());
        vo.setTimeStamp(((WxPayUnifiedOrderV3Result.JsapiResult)rawData).getTimeStamp());
        vo.setPackageValue(((WxPayUnifiedOrderV3Result.JsapiResult)rawData).getPackageValue());
        vo.setPaySign(((WxPayUnifiedOrderV3Result.JsapiResult)rawData).getPaySign());
        vo.setSignType(((WxPayUnifiedOrderV3Result.JsapiResult)rawData).getSignType());
        return vo;
    }

    public static PayOrderVo successOf(String tradeNo, String openId, String payNo, LocalDateTime successTime,  Object rawData){
        PayOrderVo vo = new PayOrderVo();
        vo.setPayStatus(PayOrderStatus.SUCCESS.getCode());
        vo.setTradeNo(tradeNo);
        vo.setOpenId(openId);
        vo.setPayNo(payNo);
        vo.setSuccessTime(successTime);
        vo.setRawData(rawData);
        vo.setReturnJson(JSONUtil.toJsonStr(rawData));
        return vo;
    }

    public static PayOrderVo of(Integer payStatus, String tradeNo, String openId, String payNo, LocalDateTime successTime,  Object rawData){
        PayOrderVo vo = new PayOrderVo();
        vo.setPayStatus(payStatus);
        vo.setTradeNo(tradeNo);
        vo.setOpenId(openId);
        vo.setPayNo(payNo);
        vo.setSuccessTime(successTime);
        vo.setRawData(rawData);
        vo.setReturnJson(JSONUtil.toJsonStr(rawData));
        return vo;
    }

    public static PayOrderVo closeOf(String errorCode, String errorMsg, String payNo, Object rawData){
        PayOrderVo vo = new PayOrderVo();
        vo.setPayStatus(PayOrderStatus.CLOSED.getCode());
        vo.setResultCode(errorCode);
        vo.setResultMsg(errorMsg);
        vo.setPayNo(payNo);
        vo.setRawData(rawData);
        vo.setReturnJson(JSONUtil.toJsonStr(rawData));
        return vo;
    }
}
